package com.lzj.framework.security;

import cn.hutool.core.util.ObjectUtil;
import com.lzj.common.constant.Constants;
import com.lzj.common.core.domain.R;
import com.lzj.common.core.domain.event.LogininforEvent;
import com.lzj.common.core.domain.model.LoginUser;
import com.lzj.common.security.service.TokenService;
import com.lzj.common.utils.JsonUtils;
import com.lzj.common.utils.MessageUtils;
import com.lzj.common.utils.ServletUtils;
import com.lzj.common.utils.spring.SpringUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 贱贱
 * @Description 注销事件处理器, 在访问注销接口时会被调用
 * <pre>
 * 通过修改 SecurityContextHolder 执行注销。
 * 如果 isInvalidateHttpSession() 是 true 且会话不是 null ，则也将使 HttpSession 无效。
 * 如果 clearAuthentication 设置为true（默认值），也将从当前 SecurityContext 中删除 Authentication 。
 * <a href="https://docs.spring.io/spring-security/site/docs/5.8.13/api/org/springframework/security/web/authentication/logout/SecurityContextLogoutHandler.html">见API文档</a>
 * </pre>
 * @Date 2024/07/16 22:43
 */
@Component
public class LogoutHandler implements LogoutSuccessHandler {
    
    @Resource
    private TokenService tokenService;

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        if (ObjectUtil.isNotNull(authentication)) {
            // 清除会话
            LoginUser loginUser = (LoginUser) authentication.getPrincipal();
            tokenService.deleteLoginUser(loginUser.getToken());
            recordLogininfor(loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"));
        }
        // 修改响应消息
        ServletUtils.renderString(response, JsonUtils.toJsonString(R.ok("注销成功")));
    }

    /**
     * 记录登录信息
     *
     * @param username 用户名
     * @param status   状态
     * @param message  消息内容
     */
    private void recordLogininfor(String username, String status, String message) {
        LogininforEvent logininforEvent = new LogininforEvent();
        logininforEvent.setUsername(username);
        logininforEvent.setStatus(status);
        logininforEvent.setMessage(message);
        logininforEvent.setRequest(ServletUtils.getRequest());
        SpringUtils.context().publishEvent(logininforEvent);
    }
    
}
